﻿HmJS.$Import('core.core');

/*
---
version: 1.3.2-0
description: A very simple class that allows stacking functions and calling them step by step or priodiacly.
license: MIT-style
download: http://mootools.net/forge/p/functionstack
source: http://github.com/arieh/FunctionStack

authors:
- Arieh Glazer

requires:
- core/1.3: [Class]

provides: [FunctionStack]

This class is different from Chain in few ways:
1. It is ment to be used as a periodical caller - the play method.
2. It is posible to pass arguments to the functions in the stack.
3. It is ment to be used as a standalone, not to be implemented by other classes. Class method names are trivial and probably will be needed by implementors (push, play, clear, reset, stop, pause).
...
*/

/*
How to use
----------

This is quite stright farward:

#JS
var stack = new FunctionStack(
function(){console.log('a');},
function(){console.log('b');},
function(){console.log('c');},
function(){console.log('d');},
function(){console.log('e');}
);
	
stack.step(); //will call log 'a'
	
stack.play(); //will log 'b' 'c' 'd' 'e' periodicaly (defualt to 1000 miliseconds)

Methods
--------

1. push (`function`[,`function`[,...]]): Recives an unlimited list of functions. Adds them to the stack.
2. step : Will call the next function in the stack. If any paramaters were sent, will send them to the function.
3. play (`int` duration, `array` args) : Will step through the stack priodicaly. If args is supplied, will pass them to the functions.
4. pause : Will pause the periodical call.
5. stop : Will stop the periodcal call, reseting the counter.
6. reset : will reset the stack index.
7. clear : will clear the stack.
*/

HmJS.register('util.FunctionStack', function ($ns) {

	return new Class({
		handle: null, //holder of interval pointer
		list: [], //stack holder
		index: 0, //current stack index
		defaultDuration: 1000, //default timeout between function calls

		initialize: function () {
			this.push.apply(this, arguments || []);
		},

		push: function () {
			this.list.append(arguments);
			this.list.clean();
		},

		step: function () {
			if (this.index < this.list.length) {
				return this.list[this.index++].apply(this, arguments || []);
			}
			return null;
		},

		play: function (duration, args) {
			this.list.erase(this._stopper);
			this.list.push(this._stopper);
			this.handle = this.step.periodical(duration || this.defaultDuration, this, args || []);
			return this;
		},

		stop: function () {
			clearInterval(this.handle);
			this.list.erase(this._stopper);
			this.reset();
			return this;
		},

		pause: function () {
			clearInterval(this.handle);
			return this;
		},

		reset: function () {
			this.index = 0;
			return this;
		},

		clear: function () {
			this.reset();
			return this;
		},

		_stopper: function () {
			this.stop();
		}

	});

});
